home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2000 February / Macworld (2000-02).dmg / Cool Extras! / DarkSide of the Mac 5.0.6 / SampleFaders / Fader.c next >
C/C++ Source or Header  |  1999-09-13  |  13KB  |  516 lines

  1. /*
  2.     DarkSide - a 7.0 dependant, system clean expandable screen saver.
  3.     
  4.     copyright © 1990-1997 by Tom Dowdy
  5.     All rights reserved.
  6.     
  7.     This fader shell serves to dispatch requests from the main DarkSide code
  8.     into the appropriate entry points.
  9. */
  10. #include <StdArg.h>
  11. #include <Memory.h>
  12. #include <Packages.h>
  13. #include <Errors.h>
  14. #include <TextUtils.h>
  15.  
  16. #include "Fader.h"
  17. #ifdef THINK_C
  18.     #include <SetupA4.h>
  19. #endif
  20.  
  21. #ifdef powerc
  22.  
  23. RoutineDescriptor preflightFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppPreflightFaderProcInfo,PreflightFader);
  24. RoutineDescriptor initializeFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppInitializeFaderProcInfo,InitializeFader);
  25. RoutineDescriptor idleFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppIdleFaderProcInfo,IdleFader);
  26. RoutineDescriptor disposeFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppDisposeFaderProcInfo,DisposeFader);
  27. RoutineDescriptor updateFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppUpdateFaderProcInfo,UpdateFader);
  28. RoutineDescriptor hitFaderUPP = BUILD_ROUTINE_DESCRIPTOR(uppHitFaderProcInfo,HitFader);
  29.    
  30. #endif
  31.     
  32. QDGlobals qd;
  33.  
  34. /* ------------------------------------------------------------------------    */
  35. /* GLOBAL HANDLING ROUTINES */
  36. /* ------------------------------------------------------------------------    */
  37. void    DebugLongInt(long aLong);
  38.  
  39. #ifndef THINK_C
  40.     OSErr    CreateA5World(Ptr * a5World);
  41.     void    DisposeA5World(Ptr a5World, Ptr appA5);
  42. #endif
  43.  
  44. /* ------------------------------------------------------------------------    */
  45. #ifndef powerc
  46.  
  47. #ifdef THINK_C
  48.     OSErr    main(long selector, Ptr *a5World, MachineInfoPtr machineInfo, ...)
  49. #else
  50.     OSErr    FaderEntry(long selector, Ptr *a5World, MachineInfoPtr machineInfo, ...)
  51. #endif
  52. {
  53.     OSErr    anErr = noErr;
  54.     va_list    nextArg;
  55.         
  56.     #ifdef THINK_C
  57.         // Set up A4 so that we can use global variables...
  58.         RememberA0();
  59.         SetUpA4();
  60.     #endif
  61.     
  62.     // start stripping optional arguments
  63.     va_start(nextArg, machineInfo);
  64.     
  65.     switch(selector)
  66.         {
  67.         case preflightFader:
  68.             {
  69.             long    *minTicks, *maxTicks;
  70.             
  71.             minTicks = va_arg(nextArg, long*);
  72.             maxTicks = va_arg(nextArg, long*);
  73.             
  74.             #ifndef THINK_C
  75.                 #ifndef powerc
  76.                     anErr = CreateA5World(a5World);
  77.                 #endif
  78.             #endif
  79.             
  80.             if (anErr == noErr)
  81.                 {
  82.                 #ifndef THINK_C
  83.                     #ifndef powerc
  84.                         (void) SetA5((long) *a5World);
  85.                     #endif
  86.                 #endif
  87.                 
  88.                 BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
  89.                 anErr = PreflightFader(machineInfo, minTicks, maxTicks);
  90.                 BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
  91.                 }
  92.             }
  93.             break;
  94.             
  95.         case initializeFader:
  96.             #ifndef THINK_C
  97.                 (void) SetA5((long) *a5World);
  98.             #endif
  99.  
  100.             BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
  101.             anErr = InitializeFader(machineInfo);
  102.             BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
  103.             break;
  104.             
  105.         case idleFader:
  106.             #ifndef THINK_C
  107.                 (void) SetA5((long) *a5World);
  108.             #endif
  109.  
  110.             anErr = IdleFader(machineInfo);
  111.             break;
  112.             
  113.         case disposeFader:
  114.             {
  115.             
  116.             #ifndef THINK_C
  117.                 (void) SetA5((long) *a5World);
  118.             #endif
  119.  
  120.             BlockMove(machineInfo->applicationQD, &qd, sizeof(qd));
  121.             anErr = DisposeFader(machineInfo);
  122.             BlockMove(&qd, machineInfo->applicationQD, sizeof(qd));
  123.  
  124.             #ifndef THINK_C
  125.                 DisposeA5World(*a5World, (Ptr)machineInfo->applicationA5);
  126.             #endif
  127.             
  128.             }
  129.             break;
  130.  
  131.         case updateFader:
  132.             #ifndef THINK_C
  133.                 (void) SetA5((long) *a5World);
  134.             #endif
  135.             anErr = UpdateFader(machineInfo);
  136.             break;
  137.             
  138.         case hitFader:
  139.             {
  140.             DialogPtr    dPtr;
  141.             long        itemHit;
  142.             long        itemOffset;
  143.                         
  144.             dPtr         = va_arg(nextArg, DialogPtr);
  145.             itemHit     = va_arg(nextArg, long);
  146.             itemOffset     = va_arg(nextArg, long);
  147.  
  148.             anErr = HitFader(machineInfo, dPtr, itemHit, itemOffset);            
  149.             }
  150.             
  151.             break;
  152.             
  153.         default:
  154.             // function not found error
  155.             anErr = fnfErr;
  156.             break;
  157.         }
  158.         
  159.     va_end(nextArg);
  160.     
  161.     #ifdef THINK_C
  162.         RestoreA4();
  163.     #else
  164.         (void) SetA5((long) machineInfo->applicationA5);
  165.     #endif
  166.     
  167.     return(anErr);    
  168.     
  169. } // FaderEntry
  170.  
  171. #endif
  172.  
  173. /* ------------------------------------------------------------------------    */
  174. /* DEBUGGING ROUTINES                             */
  175. /* ------------------------------------------------------------------------    */
  176. void DebugLongInt(long theLong)
  177. {
  178.     Str255 theString;
  179.     
  180.     NumToString(theLong, theString);
  181.     DebugStr(theString);
  182.     
  183. } // DebugLongInt
  184.  
  185.  
  186. /* ------------------------------------------------------------------------    */
  187. /* FADER UTILS                                                                 */
  188. /* ------------------------------------------------------------------------    */
  189.  
  190. Handle    BestNewHandle(Size    theSize)
  191. /*
  192.     Tries to get the handle from the temp memory first, if that fails, it goes
  193.     to the application.
  194. */
  195. {
  196.     Handle theHandle;
  197.     OSErr    anErr;
  198.     
  199.     theHandle = TempNewHandle(theSize, &anErr);
  200.     if (theHandle == nil)
  201.         theHandle = NewHandle(theSize);
  202.         
  203.     return(theHandle);
  204.     
  205. } // BestNewHandle
  206.  
  207. /* ------------------------------------------------------------------------    */
  208.  
  209. RgnHandle    BestNewRgn()
  210. /*
  211.     Tries to get a rgn handle from the temp memory first, if that fails, it goes
  212.     to the application.  Needs enough room in the app heap to create the region
  213.     in the first place.
  214. */
  215. {
  216.     RgnHandle     theRgn;
  217.     OSErr        anErr;
  218.     
  219.     // make a region
  220.     theRgn = NewRgn();
  221.     if (theRgn != nil)
  222.         {
  223.         RgnHandle    theHandle;
  224.         short        regionSize;
  225.         
  226.         // try to make something the same size in the temp memory
  227.         regionSize = GetHandleSize((Handle) theRgn);
  228.         theHandle = (RgnHandle) TempNewHandle(regionSize, &anErr);
  229.         if (anErr == noErr)
  230.             {
  231.             // if we get it, use that one for our region
  232.             BlockMove(*theRgn, *theHandle, regionSize);
  233.             DisposeRgn(theRgn);
  234.             theRgn = theHandle;
  235.             }
  236.         }
  237.         
  238.     return(theRgn);
  239.     
  240. } // BestNewRgn
  241.  
  242.  
  243.  
  244. /* ------------------------------------------------------------------------    */
  245.  
  246. short    Rnd(long max)
  247. /*
  248.     Returns a number > 0 and < max
  249. */
  250. {
  251.     unsigned long value;
  252.  
  253.     value = (unsigned short)max * (unsigned short)Random();
  254.     value >>= 16;
  255.     return(value);
  256.     
  257. } // Rnd
  258.  
  259. /* ------------------------------------------------------------------------    */
  260. void PlaceRectOnScreen(
  261.     MachineInfoPtr machineInfo,    // give info about the machine here
  262.     short width,                // width of rect, can be 0
  263.     short height,                // height of rect, can be 0
  264.     Rect * placedRect,            // Placed rect is returned here
  265.     Rect * margins,                // margins around screen, can be nil
  266.     short * whichScreen)        // screen index returned here, can be nil
  267. {
  268.     Rect        screenRect;
  269.     short        pickScreen;
  270.  
  271.     // pick a random screen    
  272.     pickScreen = Rnd(machineInfo->numScreens);
  273.     screenRect = machineInfo->theScreens[pickScreen].bounds;
  274.     if (whichScreen != nil)
  275.         *whichScreen = pickScreen;
  276.         
  277.     if (margins != nil)
  278.         {
  279.         screenRect.top += margins->top;
  280.         screenRect.left += margins->left;
  281.         screenRect.bottom -= margins->bottom;
  282.         screenRect.right -= margins->right;
  283.         }
  284.         
  285.     screenRect.right -= width;
  286.     screenRect.bottom -= height;
  287.     
  288.     if (placedRect != nil)
  289.         {
  290.         placedRect->top = screenRect.top + Rnd(screenRect.bottom - screenRect.top);
  291.         placedRect->left = screenRect.left + Rnd(screenRect.right - screenRect.left);
  292.         placedRect->bottom = placedRect->top + height;
  293.         placedRect->right = placedRect->left + width;
  294.         }
  295.         
  296. } // PlaceRectOnScreen
  297.  
  298. #ifndef THINK_C
  299. #ifndef powerc
  300. /* ------------------------------------------------------------------------    */
  301. /* FUN A5 STUFF - See Tech note 256 for details                             */
  302. /* ------------------------------------------------------------------------    */
  303. long A5Size(); 
  304. void A5Init(Ptr theA5);
  305.  
  306. OSErr    CreateA5World(Ptr * a5World)
  307. {
  308.     OSErr    anErr;
  309.     Ptr        theWorld = nil;
  310.     Handle    worldHandle;
  311.     
  312.     worldHandle = BestNewHandle(A5Size());
  313.     anErr = MemError();
  314.     if (anErr == noErr)
  315.         {
  316.         HLockHi(worldHandle);
  317.         theWorld = *worldHandle;
  318.         
  319.         theWorld += + A5Size() - 32;
  320.         A5Init(theWorld);
  321.         
  322.         // very important if anyone wants to call SwapMMUMode
  323.         theWorld = StripAddress(theWorld);
  324.         }
  325.     *a5World = theWorld;
  326.     
  327.     return(anErr);
  328.     
  329. } // CreateA5World
  330.  
  331. /* ------------------------------------------------------------------------    */
  332. void    DisposeA5World(Ptr a5World, Ptr appA5)
  333. {
  334.     
  335.     (void) SetA5((long) appA5);
  336.     
  337.     {
  338.     Handle    theHandle = RecoverHandle(a5World - A5Size() + 32);
  339.     
  340.     DisposeHandle(theHandle);
  341.     }
  342.     
  343. } // DisposeA5World
  344. #endif
  345. #endif
  346.  
  347. #ifdef THINK_C
  348. /* ------------------------------------------------------------------------    */
  349. /* CALLBACK WRAPPERS */
  350. /* ------------------------------------------------------------------------    */
  351. OSErr    WritePreferencesHandle(MachineInfoPtr machineInfo, Handle h, ResType theType)
  352. {
  353.     OSErr    anErr;
  354.     long    curA5;
  355.     long    loader;
  356.     
  357.     curA5 = SetA5((long) machineInfo->applicationA5);
  358.     loader = (long) machineInfo->callbackLoader;
  359.     asm {
  360.         move.l theType, -(SP)
  361.         move.l h, -(SP)
  362.         move.l loader, a0
  363.         moveq #0, d0
  364.         pea @returnAddress
  365.         move.l #0x08000004, -(SP)
  366.         jmp (a0)
  367.     @returnAddress:
  368.         move.w d0, anErr
  369.         add #8, SP
  370.     }
  371.     SetA5(curA5);
  372.     return(anErr);
  373.     
  374. } // WritePreferencesHandle
  375.  
  376. /* ------------------------------------------------------------------------    */
  377. OSErr    ReadPreferencesHandle(MachineInfoPtr machineInfo, Handle *h, ResType theType)
  378. {
  379.     OSErr    anErr;
  380.     long    curA5;
  381.     long    loader;
  382.     
  383.     curA5 = SetA5((long) machineInfo->applicationA5);
  384.     loader = (long) machineInfo->callbackLoader;
  385.     asm {
  386.         move.l theType, -(SP)
  387.         move.l h, -(SP)
  388.         move.l loader, a0
  389.         moveq #0, d0
  390.         pea @returnAddress
  391.         move.l #0x08000008, -(SP)
  392.         jmp (a0)
  393.     @returnAddress:
  394.         move.w d0, anErr
  395.         add #8, SP
  396.     }
  397.     SetA5(curA5);
  398.     return(anErr);
  399.     
  400. } // ReadPreferencesHandle
  401.  
  402. /* ------------------------------------------------------------------------    */
  403. // While translating this code from MPW C to THINK C I found out that the calling conventions
  404. // of these languages seem to be different. If we have a short and a Boolean as below, THINK C
  405. // pushes them both into a longword, while MPW C uses a longword for each. Very confusing!
  406.  
  407. OSErr    PlayResourceSnd(MachineInfoPtr machineInfo, long theID, Boolean async)
  408. {
  409.     OSErr    anErr;
  410.     long    loader;
  411.     
  412.     loader = (long) machineInfo->callbackLoader;
  413.     asm {
  414.         moveq #0, d0
  415.         move.b async, d0                                // convert async to longword
  416.         move.l d0, -(SP)                                // and push it
  417.  
  418.         moveq #0, d0                                    // convert theID to longword
  419.         move.w theID, d0                                // and push it
  420.         move.l d0, -(SP)
  421.         
  422.         move.l loader, a0
  423.         moveq #0, d0
  424.         pea @returnAddress                                // push return address
  425.         move.l #0x0800000C, -(SP)                        // push selector code
  426.         jmp (a0)                                        // jump to callback loader
  427.     @returnAddress:
  428.         move.w d0, anErr                                // save result code                                
  429.         add #8, SP                                        // adjust stack
  430.     }
  431.     return anErr;
  432.     
  433. } // PlayResourceSnd
  434.  
  435. #else
  436.  
  437. /* ------------------------------------------------------------------------    */
  438. /* CALLBACK DEFINES */
  439. /* ------------------------------------------------------------------------    */
  440. #ifndef powerc
  441.     #pragma parameter __D0 DoWritePreferencesHandle(__A0)
  442.     OSErr DoWritePreferencesHandle(Ptr M, Handle h, ResType theType) = 
  443.         { 0x7000, 0x487B, 0x000A, 0x2F3C, 0x0800, 0x0004, 0x4ED0};
  444.     #pragma parameter __D0 DoReadPreferencesHandle(__A0)
  445.     OSErr DoReadPreferencesHandle(Ptr M, Handle *h, ResType theType) = 
  446.         { 0x7000, 0x487B, 0x000A, 0x2F3C, 0x0800, 0x0008, 0x4ED0};
  447. //    #pragma parameter __D0 DoPlayResourceSnd(__A0)
  448.     OSErr DoPlayResourceSnd(Ptr M, long theID, long async) = 
  449.         {     0x205f, // MOVEA.L (SP)+, A0
  450.             0x7000,     // MOVEQ 0, D0
  451.             0x487B, 0x000A, // PEA *+C(D0)
  452.             0x2F3C, 0x0800, 0x000C, // MOVE SELECTOR, -(SP)
  453.             0x4ED0}; // JMP (A0)
  454. #endif
  455.  
  456. /* ------------------------------------------------------------------------    */
  457. /* CALLBACK WRAPERS */
  458. /* ------------------------------------------------------------------------    */
  459. OSErr    WritePreferencesHandle(MachineInfoPtr machineInfo, Handle h, ResType theType)
  460. {
  461.     OSErr    anErr;
  462.  
  463.     #ifdef powerc
  464.         anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackWritePreferencesHandle, h, theType);
  465.     #else
  466.         long    curA5;
  467.         
  468.         curA5 = SetA5((long)machineInfo->applicationA5);
  469.         anErr = DoWritePreferencesHandle(machineInfo->callbackLoader, h, theType);
  470.         SetA5(curA5);
  471.     #endif
  472.     
  473.     return(anErr);
  474.     
  475. } // WritePreferencesHandle
  476.  
  477. /* ------------------------------------------------------------------------    */
  478. OSErr    ReadPreferencesHandle(MachineInfoPtr machineInfo, Handle *h, ResType theType)
  479. {
  480.     OSErr    anErr;
  481.  
  482.     #ifdef powerc
  483.         anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackReadPreferencesHandle, h, theType);
  484.     #else
  485.         long    curA5;
  486.         
  487.         curA5 = SetA5((long)machineInfo->applicationA5);
  488.         anErr = DoReadPreferencesHandle(machineInfo->callbackLoader, h, theType);
  489.         SetA5(curA5);
  490.     #endif
  491.     
  492.     return(anErr);
  493.     
  494. } // ReadPreferencesHandle
  495.  
  496. /* ------------------------------------------------------------------------    */
  497. OSErr    PlayResourceSnd(MachineInfoPtr machineInfo, long theID, long async)
  498. {
  499.     OSErr    anErr;
  500.  
  501.     #ifdef powerc
  502.         anErr = CallUniversalProc((UniversalProcPtr) machineInfo->callbackLoader, uppCallbackInfo, callbackPlayResourceSnd, (long)theID, (long)async);
  503.     #else
  504.         long    curA5;
  505.         
  506.         curA5 = SetA5((long)machineInfo->applicationA5);
  507.         anErr = DoPlayResourceSnd(machineInfo->callbackLoader, theID, async);
  508.         SetA5(curA5);
  509.     #endif
  510.     
  511.     return(anErr);
  512.     
  513. } // PlayResourceSnd
  514.  
  515. #endif
  516.